package com.starview.star.operators.relation.runtime;

import java.util.ArrayList;
import java.util.List;

import com.starview.platform.data.EvaluationException;
import com.starview.platform.data.IConstructor;
import com.starview.platform.data.IFunction;
import com.starview.platform.data.IMap;
import com.starview.platform.data.IValue;
import com.starview.platform.data.type.IType;
import com.starview.platform.data.type.Refresher;
import com.starview.platform.data.type.StandardTypes;
import com.starview.platform.data.type.TypeUtils;
import com.starview.platform.data.type.TypeVar;
import com.starview.platform.data.value.Factory;
import com.starview.platform.data.value.NTuple;
import com.starview.star.operators.CafeEnter;

public class ExtendKeys implements IFunction
{

  public static final String name = "__extendKeys";

  @CafeEnter
  public static IConstructor enter(IConstructor keySource, IConstructor cols, IConstructor keys, IMap extraMap)
      throws EvaluationException
  {
    List<IValue> eKeys = null;

    for (int ix = 0; ix < cols.size(); ix++) {
      IValue col = cols.getCell(ix);
      IValue rCol = extraMap.getMember(col);
      if (rCol != null) {
        if (eKeys == null)
          eKeys = new ArrayList<IValue>();
        eKeys.add(keys.getCell(Factory.intValue(rCol)));
      }
    }

    if (eKeys == null)
      return keySource;
    else {
      int colSize = keySource.size();
      IValue[] newCols = new IValue[colSize + eKeys.size()];
      for (int ix = 0; ix < colSize; ix++)
        newCols[ix] = keySource.getCell(ix);

      for (IValue col : eKeys)
        newCols[colSize++] = col;

      assert colSize == newCols.length;

      return NTuple.tuple(newCols);
    }
  }

  @Override
  public IValue enter(IValue... args) throws EvaluationException
  {
    return enter((IConstructor) args[0], (IConstructor) args[1], (IConstructor) args[2], (IMap) args[3]);
  }

  @Override
  public IType getType()
  {
    return type();
  }

  public static IType type()
  {
    // This type is a bit hokey.
    return Refresher.generalize(TypeUtils.functionType(new TypeVar(), new TypeVar(), new TypeVar(), TypeUtils.hashType(
        StandardTypes.integerType, StandardTypes.integerType), new TypeVar()));
  }
}